home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac-Source 1994 July
/
Mac-Source_July_1994.iso
/
C and C++
/
Graphics⁄Sound
/
Contours source
/
fractal2.c
< prev
Wrap
Text File
|
1985-09-03
|
7KB
|
282 lines
/*
' 3-Dimensional Fractal surface generating program
' From July '85 Creative Computing.
*/
#include <quickdraw.h>
#include <toolutil.h>
#define watchCursor 4 /* Should be in TOOLUTIL.H but isn't. JEC */
double ran(); /* Should be in MATH.H but isn't. JEC */
#include "fractal.h"
#define TRUE (-1)
#define FALSE 0
int linestart; /* True at the first of the line. */
int color; /* True when plotting land, else false. */
calcsurf(level)
int level;
{
int i, j, length, incrby, sk;
float power;
CursHandle ticktock;
if (!points)
return;
ticktock = GetCursor(watchCursor);
if (ticktock)
SetCursor(*ticktock); /* Show watch (wait) */
xmax = 1 << level;
ymax = xmax/2;
for (i=0; i<=xmax; i++) /* Clear the Array. Use i & incrby as temps. */
for (incrby=0; incrby<=ymax; incrby++)
(*points)[i][incrby] = 0;
for (i=1; i<= level; i++) {
for (power=1.0, j=0; j<i; j++)
power *= 1.8;
length = 10000/power; /* = 10000/(1.8^i) */
incrby = xmax/(1 << i); /* # of line segments in a side of the triangle. */
sk = incrby * 2;
calcxs(length, incrby, sk);
calcys(length, incrby, sk);
calcdiags(length, incrby, sk);
}
InitCursor(); /* Put back the arrow. */
}
calcxs(len, incr, sk) /* Assign heights along x in array. */
int len;
register int incr, sk;
{
register int y, x;
int d1, d2;
for (y=0; y < xmax; y += sk) {
for (x = incr+y; x <= xmax; x += sk) {
d1 = getdata(x-incr, y);
d2 = getdata(x+incr, y);
stuffdata(((d1+d2)>>1) + (int)(ran()*(len>>1)) - (len>>2), x, y);
}
}
}
calcys(len, incr, sk) /* Assign heights along y in array. */
int len;
register int incr, sk;
{
register int y, x;
int d1, d2;
for (x=xmax; x >= 1; x -= sk)
for (y = incr; y <= x; y += sk) {
d1 = getdata(x, y+incr);
d2 = getdata(x, y-incr);
stuffdata(((d1+d2)>>1) + (int)(ran()*(len>>1)) - (len>>2), x, y);
}
}
calcdiags(len, incr, sk) /* Assign heights along diagonal in array. */
int len;
register int incr, sk;
{
register int y, x;
int d1, d2;
for (x=0; x < xmax; x += sk)
for (y = incr; y <= xmax-x; y += sk) {
d1 = getdata(x+y-incr, y-incr);
d2 = getdata(x+y+incr, y+incr);
stuffdata(((d1+d2)>>1) + (int)(ran()*(len>>1)) - (len>>2), x+y, y);
}
}
getdata(x, y)
register int x, y;
{
if (y <= ymax)
return (*points)[x][y];
else
return (*points)[xmax-x][xmax+1-y];
}
stuffdata(d, x, y)
register int d, x, y;
{
if (y <= ymax)
(*points)[x][y] = d;
else
(*points)[xmax-x][xmax+1-y] = d;
}
/*
** Our window is already open at this point, and it is cleared,
** all we have to do now is fill it.
** Draw the 2D projection of the triangular database on the screen.
*/
plotdata()
{
register int xindex, yindex;
if (!points)
return;
color = TRUE; /* On land to start. */
for (xindex=0; xindex<=xmax; xindex++) { /* Plot along X axis. */
linestart = TRUE;
for (yindex=0; yindex<=xindex; yindex++)
doplot(xindex, yindex);
}
for (yindex=0; yindex<=xmax; yindex++) { /* Plot along Y axis. */
linestart = TRUE;
for (xindex=yindex; xindex<=xmax; xindex++)
doplot(xindex, yindex);
}
for (xindex=0; xindex<=xmax; xindex++) { /* Plot along the diagonal. */
linestart = TRUE;
for (yindex=0; yindex<=xmax-xindex; yindex++)
doplot(xindex+yindex, yindex);
}
}
doplot(xindex, yindex)
int xindex, yindex;
{
int xcoord, ycoord, zcoord;
zcoord = getdata(xindex, yindex);
ycoord = scaler(yindex, 10000, xmax);
xcoord = scaler(xindex, 10000, xmax) - ycoord/2;
if (conttype == SETUPWATR)
sealevel(&xcoord, &ycoord, &zcoord);
plotto(xcoord, ycoord, zcoord);
}
sealevel(newx, newy, newz)
int *newx, *newy, *newz;
{
static int oldx, oldy, oldz; /* The starting point for the next call. */
int waterx, watery, waterz; /* Where the vector hits the waterline. */
float scratch;
if (linestart) { /* If at the beginning of the line */
if ((oldz = *newz) < 0) { /* and if we're underwater. */
color = FALSE;
*newz = 0; /* Clip to the waterline. */
}
else
color = TRUE; /* Otherwise we're on land from the start. */
}
else { /* Else we're in the middle of a line and ... */
if (oldz > 0 && *newz > 0) { /* start & end points both above water.. */
oldz = *newz;
}
else if (oldz < 0 && *newz < 0) { /* start & end points both under water... */
oldz = *newz;
*newz = 0; /* Clip at the waterline */
}
else { /* We're now crossing the waterline, */
/* so calculate the exact point where it dives under. */
scratch = (float) (*newz)/(*newz-oldz); /* Proportion of the line that's */
waterx = (int) ((oldx - *newx)*scratch) + *newx; /* below the water. */
watery = (int) ((oldy - *newy)*scratch) + *newy;
waterz = 0;
plotto(waterx, watery, waterz); /* Draw to the waterline first. */
/* The plot from the waterline to the endpoint in the new color
is done elsewhere. */
if (*newz > 0) { /* Emerging from the water. */
color = TRUE; /* Set new color to 'land'. */
oldz = *newz;
}
else { /* Diving into the water. */
color = FALSE; /* Set new color to 'sea'. */
oldz = *newz;
*newz = 0;
}
}
}
oldx = *newx; /* Save the real endpoint of the vector */
oldy = *newy; /* to use as the start of the next call. */
/* (Z taken care of individually above). */
}
scaler(base, numer, denom) /* Computes base*numer/denom with long intermediate.
*/
register int base, numer, denom;
{
register long temp;
temp = (long) base * (long) numer;
temp /= (long) denom;
return (int) temp;
}
plotto(x, y, z) /* Convert 3-D line to a 2-D line and plot it. */
int x, y, z;
{
rotate(&x, &y); /* Rotate 30 deg. towards Y in the XY plane */
tiltdown(&x, &z); /* Tip 36 deg. down in the ZX plane */
x /= 25; /* Scale 10K to 400. */
y /= 25;
z /= 25;
drawline(y, z); /* Show the YZ planar projection. */
}
rotate(x, y) /* Rotate XY plane 30 deg positive. */
int *x, *y;
{
cordic(x, y, 5, 17);
}
tiltdown(x, z) /* Rotate XZ plane 36 deg negative (+?). */
int *x, *z;
{
cordic(x, z, 5, (conttype == SETUPMTN) ? 20 : -20);
}
drawline(x, y) /* Draw either a line from the last endpoint */
int x, y; /* to the given point, or only a point at x,y. */
{
static int lastx, lasty;
x += x/10 + 10; /* Quick x1.1 + tiny offset. */
if (conttype == SETUPMTN)
y = 220 - y; /* Move the baseline for mountains. */
else
y = 80 - y;
if (linestart || !color) /* Only a point then. */
MoveTo(x, y);
LineTo(x, y);
lastx = x;
lasty = y;
linestart = FALSE; /* Stuck in the middle with you... */
}
cordic(x, y, scale, count) /* Spin XY vector 'count' steps to the left using */
int *x, *y; /* CORDIC algorithm with a shift factor of 'scale'. */
register int scale, count; /* Rotates atan(1/(2^scale)) degrees/step. */
/* (Scale of 5 is 1.79 deg/step; 4 = 3.57 d/s...) */
/* *x & *y should be large for accuracy. */
{
register int tempx, tempy;
tempx = *x;
tempy = *y;
if (count>0) /* Positive count is CCW (left) */
for (; count; count--) {
tempx -= (tempy>>scale);
tempy += (tempx>>scale);
}
else /* Negative is CW (right) */
for (; count; count++) {
tempx += (tempy>>scale);
tempy -= (tempx>>scale);
}
*x = tempx;
*y = tempy;
}